package com.stockz.ui.swing.scanner;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Box;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;
import org.hsqldb.lib.StringUtil;
import org.metawidget.swing.SwingMetawidget;
import org.metawidget.swing.widgetprocessor.binding.beanutils.BeanUtilsBindingProcessor;

import com.stockz.core.model.Scrip;
import com.stockz.scanner.Scanner;
import com.stockz.scanner.callback.ScannerCallback;
import com.stockz.scanner.model.ScannerEvent;
import com.stockz.scanner.model.ScannerEvent.EventType;
import com.stockz.ui.swing.charting.display.screen.AbstractDisplayableScreenConfiguration;
import com.stockz.ui.swing.charting.widget.ScreenNameComboBox;
import com.stockz.ui.swing.core.MainFrame;
import com.stockz.ui.swing.util.JProgressBarUpdater;
import com.stockz.ui.swing.widget.FilteredComboBox.OnSelectionCallback;
import com.stockz.ui.swing.widget.JButton;
import com.stockz.ui.swing.widget.JTextField;
import java.awt.GridLayout;

public class ScannerPanel extends JPanel {
	private static final long serialVersionUID = -5990803815406419096L;
	private static final Logger logger = Logger.getLogger(ScannerPanel.class);

	private final JLabel probingSpanLabel = new JLabel("Probing Span");
	private final JTextField probingSpanTextField = new JTextField();
	private final JLabel offsetLabel = new JLabel("Offset");
	private final JTextField offsetTextField = new JTextField();
	private final ScreenNameComboBox screenNameComboBox = new ScreenNameComboBox();
	private final JButton scanButton = new JButton("Scan");
	private final JButton cancelButton = new JButton("Cancel");
	private final JProgressBar progressBar = new JProgressBar();
	private final JLabel totalLabel = new JLabel("Total : ");
	private final JLabel totalValueLabel = new JLabel();
	private final JLabel scannedLabel = new JLabel("Scanned : ");
	private final JLabel scannedValueLabel = new JLabel();
	private final JLabel skippedLabel = new JLabel("Skipped : ");
	private final JLabel skippedValueLabel = new JLabel();
	private final JLabel matchedLabel = new JLabel("Matches : ");
	private final JLabel matchedValueLabel = new JLabel();
	private final JPanel screenConfigurationPanel = new JPanel();
	private final JPanel progressPanel = new JPanel();
	private final SwingMetawidget swingMetaWidget = new SwingMetawidget();
	private final BeanUtilsBindingProcessor beanUtilsBindingProcessor 
				= new BeanUtilsBindingProcessor();
	private final Scanner scanner = new Scanner();
	private final ScanResultPanel scanResultPanel;
	AbstractDisplayableScreenConfiguration screen;
	private final Component horizontalGlue = Box.createHorizontalGlue();
	private final Component horizontalGlue_1 = Box.createHorizontalGlue();
	private final Component horizontalGlue_2 = Box.createHorizontalGlue();
	
	public ScannerPanel(ScanResultPanel resultPanel) {
		this.scanResultPanel = resultPanel;
		setLayout(new BorderLayout(0, 0));
		swingMetaWidget.addWidgetProcessor(beanUtilsBindingProcessor);
		JPanel panel = new JPanel();
		OnSelectionCallback onSelectionCallback = new OnSelectionCallback(){
			@Override
			public void onSelection(Object selectedItem) {
				screen = (AbstractDisplayableScreenConfiguration)selectedItem;
				swingMetaWidget.setToInspect(screen.getConfiguration());
				screenConfigurationPanel.add(swingMetaWidget);
				screenConfigurationPanel.repaint();
			}
		};
		panel.setLayout(new GridLayout(0, 2, 10, 10));
		panel.add(probingSpanLabel);
		probingSpanTextField.setText(String.valueOf(scanner.getProbingSpan()));
		panel.add(probingSpanTextField);
		
		panel.add(offsetLabel);
		offsetTextField.setText(String.valueOf(scanner.getOffset()));
		panel.add(offsetTextField);
		
		screenNameComboBox.setOnSelectionCallback(onSelectionCallback);
		panel.add(screenNameComboBox);
		scanButton.addActionListener(new ActionListener(){
			
			public void actionPerformed(ActionEvent e){
				scanButton.setEnabled(false);
				cancelButton.setEnabled(true);
				progressPanel.setVisible(true);
				swingMetaWidget.getWidgetProcessor(BeanUtilsBindingProcessor.class).save(swingMetaWidget);
				final List<ScannerCallback> scannerCallbackList = new ArrayList<ScannerCallback>();
				
				ScannerCallback scannerCallback = new ScannerCallback(){
					@Override
					public void onScannerEvent(ScannerEvent e) {
						if(EventType.OnScanStart.equals(e.getEventType())){
							swingMetaWidget.setEnabled(false);
							progressBar.setMaximum(e.getTotalScripCount());
							DefaultTableModel atm = (DefaultTableModel)scanResultPanel.getTable().getModel();
							atm.getDataVector().clear();
							atm.fireTableDataChanged();
							//scanResultPanel.getTable().repaint();
							totalValueLabel.setText(String.valueOf(e.getTotalScripCount()));
							
							JProgressBarUpdater.update(progressBar, e.getCurrentScripIndex());
							scannedValueLabel.setText(String.valueOf(e.getCurrentScripIndex()));
							skippedValueLabel.setText(String.valueOf(e.getTotalSkippedCount()));
							matchedValueLabel.setText(String.valueOf(e.getTotalMatchCount()));
							
							
						}
						if(EventType.OnScanEnd.equals(e.getEventType())
								|| EventType.OnScanCancel.equals(e.getEventType())){
							scanButton.setEnabled(true);
							cancelButton.setEnabled(false);
							swingMetaWidget.setEnabled(true);
							JProgressBarUpdater.update(progressBar, e.getTotalScripCount());
							//progressPanel.setVisible(false);
						}
						if(EventType.OnScripScanEnd.equals(e.getEventType())){
							JProgressBarUpdater.update(progressBar, e.getCurrentScripIndex());
							scannedValueLabel.setText(String.valueOf(e.getCurrentScripIndex()));
							skippedValueLabel.setText(String.valueOf(e.getTotalSkippedCount()));
							matchedValueLabel.setText(String.valueOf(e.getTotalMatchCount()));
						}
						if(EventType.OnMatch.equals(e.getEventType())){
							matchedValueLabel.setText(String.valueOf(e.getTotalMatchCount()));
							DefaultTableModel atm = (DefaultTableModel)scanResultPanel.getTable().getModel();
							atm.addRow(new Scrip[]{e.getScrip()});
						}
					}
				};
				scannerCallbackList.add(scannerCallback);
				new Thread(){
					@Override
					public void run() {
						super.run();
						try {
							
							try{
								String strProbingSpan = probingSpanTextField.getText();
								if(!StringUtil.isEmpty(strProbingSpan)){
									scanner.setProbingSpan(Integer.parseInt(strProbingSpan.trim()));									
								}
							}catch(NumberFormatException pe){
								JOptionPane.showMessageDialog(MainFrame.getInstance(),
									    pe.getMessage(),
									    "Invalid Probing Span",
									    JOptionPane.ERROR_MESSAGE);
							}
							
							try{
								String strOffset = offsetTextField.getText();
								if(!StringUtil.isEmpty(strOffset)){
									scanner.setOffset(Integer.parseInt(strOffset.trim()));									
								}
							}catch(NumberFormatException pe){
								JOptionPane.showMessageDialog(MainFrame.getInstance(),
									    pe.getMessage(),
									    "Invalid Offset",
									    JOptionPane.ERROR_MESSAGE);
							}
							
							scanner.scan(screen.getScreen(), scannerCallbackList);
						} catch (Exception e1) {
							logger.error("Scanner Failure", e1);
							scanButton.setEnabled(true);
							cancelButton.setEnabled(false);
							JOptionPane.showMessageDialog(MainFrame.getInstance(),
								    e1.getMessage(),
								    "Error",
								    JOptionPane.ERROR_MESSAGE);
						}
					}
				}.start();
			}
		});
		JPanel panel1 = new JPanel();
		panel1.add(scanButton);
		cancelButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				scanner.cancel();
				scanButton.setEnabled(true);
				cancelButton.setEnabled(false);
			}
		});
		panel1.add(cancelButton);
		panel.add(panel1);
		
		add(panel, BorderLayout.NORTH);
		add(screenConfigurationPanel, BorderLayout.CENTER);
		
		
		progressPanel.setLayout(new BorderLayout(0, 0));
		JPanel infoPanel = new JPanel();
		infoPanel.add(totalLabel);
		infoPanel.add(totalValueLabel);
		
		infoPanel.add(horizontalGlue);
		infoPanel.add(scannedLabel);
		infoPanel.add(scannedValueLabel);
		
		infoPanel.add(horizontalGlue_1);
		infoPanel.add(skippedLabel);
		infoPanel.add(skippedValueLabel);
		
		infoPanel.add(horizontalGlue_2);
		infoPanel.add(matchedLabel);
		infoPanel.add(matchedValueLabel);
		progressPanel.add(infoPanel, BorderLayout.NORTH);
		progressPanel.add(progressBar);
		progressBar.setStringPainted(true);
		add(progressPanel, BorderLayout.SOUTH);
		progressPanel.setVisible(false);
		
	}
	
}
